<?php
namespace src\logic;
use \classlib\core as C;
class limapi {
	/**
	 * 默认非注册用户凌晨5点uid过期
	 * @var unknown
	 */
	const HOUR   = 5;
	
	/**
	 * 存储成员数量的key资料 sortedset
	 * @var string
	 */
	const CMKEY  = 'smc';
	
	/**
	 * 定义匿名的用户uin资料信息
	 * @var int
	 */
	const INTBASE = 0x80000000;
	
	/**
	 * 获取设置的Tocken 存储Key
	 * @param int $uin
	 * @return string
	 */
	public static function ckey($uin) {
		return 'im_'.$uin;
	}
	
	/**
	 * 获取设置的IM-状态服务Redis
	 * @return Redis $redis
	 */
	private static function redis() {
		static $redis = null;
		if (!$redis) {
			$config = C\config::load('im', false);
			$redis  = new \Redis();
			if (!$redis->connect($config['redis']['host'], $config['redis']['port'], $config['redis']['timeout'])) {
				$redis = null;
				return false;
			}
			if (isset($config['redis']['dbuse'])) {
				$redis->select($config['redis']['dbuse']);
			}
		}
		return $redis;
	}
	
	/**
	 * 获取用户当前在哪个直播间
	 * @param unknown $userid
	 * @return int $studioid
	 */
	public static function studioid($userid) {
		$redis = self::redis();
		if(!$redis) {
			return 0;
		}
		return $redis->get('memberstudio_'.$userid);
	}
	
	/**
	 * 获取一个过期时间,设定统一凌晨5点过期
	 * @return int $expire
	 */
	public static function expire() {
		$hour   = date('G');
		$expire = C\config::$nowtime + 86400;
		if ($hour < self::HOUR) { //不足凌晨5点补齐
			$expire += (self::HOUR - $hour) * 3600;
		} else if ($hour > self::HOUR) {
			$expire -= ($hour - self::HOUR) * 3600;
		}
		return $expire;
	}
	
	/**
	 * 注册IM连接的验证Tocken
	 * @param int $uin    会员绑定的uin，匿名用户也会有一个
	 * @param int $userid 会员的id编号
	 * @param string $token
	 * @return bool
	 */
	public static function regtoken($uin, $userid, $token) {
		$redis = \classlib\cache::inst('redis')->inst();
		$ckey  = self::ckey($uin);
		$data  = array('uin'=>$userid, 'token'=>$token);
		if (!$redis->hMset($ckey, $data)) {
			return false;
		}
		//对于未过期的用户设置过期时间
		if ($userid < 1) {
			$expire = self::expire();
			$redis->expireAt($ckey, $expire);
		}
		return true;
	}
	
	/**
	 * 获取IM请求token
	 * @param int $uin
	 * @return string
	 */
	public static function gettoken($uin) {
		$redis = \classlib\cache::inst('redis')->inst();
		$ckey  = self::ckey($uin);
		$token = $redis->hGet($ckey, 'token');
		return $token;
	}
	
	/**
	 * 获取请求的验证Key资料信息
	 * @param string $studioids
	 */
	public static function keystatus($studioids) {
		$skey = md5($studioids.'^&$f*^#%d#@g*&g');
		return substr($skey, 8, 16);
	}
	
	/**
	 * 获取直播间会员数量信息
	 * @param array $studioids
	 * @return array map[id=>num]
	 */
	public static function getolstat($studioids) {
		$stats = array();
		$redis = self::redis();
		if (!$redis) {
			return $stats;
		}
		foreach ($studioids as $sid) {
			$snum        = $redis->zScore(self::CMKEY, $sid);
			$status      = $redis->hGet('studio_'.$sid, 'status');
			if ($status != 1) {
				$status  = 0;
			}
			$stats[$sid] = array(intval($snum), intval($status)); 
		}
		return $stats;
	}
	
	/**
	 * 获取http imapi地址
	 * @return string
	 */
	public static function imuri() {
		$config = C\config::load('im', false);
		$idx    = C\config::$nowtime % count($config['api']);
		$api    = 'http://'.$config['api'][$idx];
		return $api;
	}
	
	/**
	 * 获取直播间中在线的用户统计
	 * @param array $sids
	 * @param array
	 */
	public static function getoluserstat($sids) {
		$stat = array();
		$api  = self::imuri().'/getstudiostatistics';
		$data = array('Count'=>count($sids), 'StudioIdList'=>$sids);
		$res  = \classlib\request::run($api, json_encode($data));
		if ($res['code'] == 0) {
			$res = json_decode($res['msg'], true);
			if (isset($res['StudioStatisticsList']) && !empty($res['StudioStatisticsList'])) {
				foreach ($res['StudioStatisticsList'] as $item) {
					$stat[$item['StudioId']] = array('total'=>$item['TotalCount'], 
						'normal'=>$item['NormalCount'], 'robot'=>$item['RobotCount'],
						'visitor'=>$item['VisitorCount']);
				}
			}
		}
		return $stat;
	}
	
	/**
	 * 获取直播间成员数排行
	 * @return array map[id=>num]
	 */
	public static function getolnums() {
		$stats = array();
		$redis = self::redis();
		if (!$redis) {
			return $stats;
		}
		$stats = $redis->zRange(self::CMKEY, 0, -1, 'WITHSCORES');
		return $stats;
	}
	
	/**
	 * 获取一个直播间的在线人数资料信息
	 * @param int $studioid
	 * @return int
	 */
	public static function getolbyid($studioid) {
		$redis = self::redis();
		if (!$redis) {
			return 0;
		}
		$stats = $redis->zScore(self::CMKEY, $studioid);
		return intval($stats);
	}
	
	/**
	 * 通知C++直播间状态信息
	 * @param int $studioid  当前房间号
	 * @param int $status    状态 0-直播停止 1-直播中
	 * @param int $rtocken   验证Tokcen
	 * @param int $eventid   当前场景id 房间创建时场景为0
	 * @param int $anchoruid 当前房间主播id
	 */
	public static function notifystatus($studioid, $anchoruid, $rtocken, $status=0, $eventid=0) {
		$data = array('StudioId'=>$studioid, 'Status'=>$status, 'EventId'=>$eventid, 'AnchorUin'=>$anchoruid);
		if ($status == 1) { //直播中
			$studio = C\model::load('live.vs.studio')->get_one($studioid);
			$rtmps  = lrtmp::recv($studioid, $eventid);
			$data['RecvRtmpCount'] = count($rtmps);
			$data['RecvRtmpList']  = array();
			foreach ($rtmps as $rtmp) {
				$data['RecvRtmpList'][] = array('Buff'=>$rtmp);
			}
		}
		$api    = self::imuri().'/notifystudiostatus';
		$res    = self::async($api, json_encode($data, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));
		return $res;
	}
	
	/**
	 * 获取IM连接地址信息
	 * @return string
	 */
	public static function im() {
		$config = C\config::load('im', false);
		$idx    = C\config::$nowtime % count($config['im']);
		$imconf =  $config['im'][$idx];
		return $imconf;
	}
	
	/**
	 * 获取IM连接地址信息
	 * @return string
	 */
	public static function ims() {
		$maxlen = 3;
		$config = C\config::load('im', false);
		$len    = count($config['im']);
		if ($len < $maxlen) {
			return $config['im'];
		}
		$keys   = array_rand($config['im'], $maxlen);
		$list   = array();
		foreach ($keys as $idx) {
			$list[] = $config['im'][$idx];
		}
		return $list;
	}
	
	/**
	 * 更新直播间的粉丝人数广播
	 * @param int $studioid
	 * @param int $ttl
	 */
	public static function notifyfocus($studioid, $ttl) {
		$data   = array('studioid'=>$studioid, 'focuscount'=>$ttl);
		$data   = \classlib\request::querystr($data);
		$api    = self::imuri().'/notifyfocuschange';
		$header = array();
		return self::async($api, $data, $header, 'GET');
	}
	
	/**
	 * 关键词过滤 0-内容过滤  1-加载字典
	 * @param int    $type
	 * @param string $msg 
	 */
	public static function filter($type, $msg='') {
		$api    = self::imuri().'/filterstring?optype='.$type;
		$res    = \classlib\request::run($api, $msg);
		if($res['code'] != 0) {
			return false;
		}
		$res    = json_decode($res['msg'], true);
		if ($type == 2 && $res && $res['ResultContent']) {
			$res['ResultContent'] = 1;
		}
		return $res;
	}
	
	/**
	 * 对直播间广播发送消息
	 * @param unknown $studioid
	 * @param unknown $msg 当中的mtype 1-管理员身份变动 2-会员主播经验变动 3-会员等级变动 4-购买vip
	 * @param number $uin
	 * @param number $mtype
	 */
	public static function notifystudio($studioid, $msg, $uin = 0, $mtype=20013) {
		$data   = array('StudioId'=>$studioid, 'MsgContent'=>$msg, 'ToUin'=>$uin, 'MsgType'=>$mtype);
		$api    = self::imuri().'/sendmsg';
		return self::async($api, json_encode($data));
	}
	
	/**
	 * 开播提醒关注的用户
	 * @param array $user
	 * @param array $studio
	 * @return mix
	 */
	public static function notifystart(&$user, &$studio) {
		$uids   = luser::myfocus($studio['userid'], 0);
		if (!empty($uids)) {
			$avtar  = $user['thumb'];
			$link   = C\router::get_url('live', $studio['studiono']);
			$data   = array('StudioId'=>$studio['id'], 'AnchorUin'=>$studio['userid'], 'StudioUrl'=>$link,
				'AnchorName'=>$user['nickname'], 'HeadImgUrl'=>$avtar, 'FocusCount'=>count($uids), 'FocusList'=>$uids);
			$api    = self::imuri().'/focuslivestartnotify';
			return self::async($api, json_encode($data));
		}
		return true;
	}
	
	/**
	 * 主播在开播前3分钟提醒关注的用户(发邮件)
	 * @param array $user
	 * @param array $studio
	 * @return mix
	 */
	public static function notifyfans(&$user, &$studio) {
		$uids   = luser::myfocus($studio['userid'], 0);
		if (!empty($uids)) {//给关注用户发邮件
			$config= C\config::load('config', false);
			$uorm  = C\model::load('main.pl.userinfo');
			$link  = $config['website'].C\router::get_url('live', $studio['studiono']);
			$unsub = $config['website'].C\router::get_url('profile/setting', 'unsubscribe');
			foreach ($uids as $uid) {
				$one    = $uorm->set_dev($uid)->get_one($uid);
				if($one && !(intval($one['mailnotify']) & 0x02)) {
					continue;
				}
				$skey   = \classlib\crypt\xxtea::encrypt($one['userid']);
				$data   = lmailer::tpl_compiler(array('url'=>$link, 'nickname'=>$one['nickname'], 'broadcaster'=>$user['nickname'],
					'airtime'=>lshare::timezone($studio['airtime']), 'unsub'=>$unsub.'?s='.urlencode($skey)), 50012);
				if ($data) {
					$title  = str_replace('name', $user['nickname'], $data['title']);
					lmailer::send($title, $data['tpl'], $one['email']);
				}
			}
			$data   = array('StudioId'=>$studio['id'], 'AnchorUin'=>$studio['userid'], 'StudioUrl'=>$link,
				'AnchorName'=>$user['nickname'], 'HeadImgUrl'=>$user['thumb'], 'FocusCount'=>count($uids), 'FocusList'=>$uids);
			$api    = self::imuri().'/focuslivestartnotify';
			return self::async($api, json_encode($data));
		}
		return true;
	}
	
	/**
	 * type为超时类型 0--禁言用户 1--踢出用户 2---屏蔽用户
	 * @param number $type
	 * @return array $res
	 */
	public static function getlimitlen($type=1) {
		$api = self::imuri().'/gettimelimit?limittype='.$type;
		$res = \classlib\request::run($api, '', array(), 'GET');
		if ($res['code'] != 0) {
			return false;
		}
		$res = json_decode($res['msg'], true);
		return ($res && $res['Result'] == 1)? $res['LimitLen']:false;
	}
	
	/**
	 * 设置过期时间
	 * @param number $type
	 * @param number $limitlen
	 * @return array $res
	 */
	public static function setlimitlen($type=1, $limitlen=1200) {
		$api = self::imuri().'/settimelimit?limittype='.$type.'&limitlen='.$limitlen;
		$res = \classlib\request::run($api, '', array(), 'GET');
		return $res;
	}
	
	/**
	 * 给指定的直播间新增机器人
	 * @param int    $studioid
	 * @param array  $userids
	 * @return array $res
	 */
	public static function addrobotlist($studioid, $userids) {
		$api  = self::imuri().'/addrobotlist';
		$data = array('Count'=>count($userids), 'RobotList'=>array());
		foreach ($userids as $userid) {
			$data['RobotList'][] = array('StudioId'=>$studioid, 'Uin'=>$userid);
		}
		$res = \classlib\request::run($api, json_encode($data));
	}
	
	/**
	 * 获取指定直播间的机器人
	 * @param int    $studioid
	 * @return array $res
	 */
	public static function getrobotlist($studioid) {
		$api  = self::imuri().'/getrobotlist';
		$data = array('Count'=>1, 'StudioIdList'=>array($studioid));
		$res  = \classlib\request::run($api, json_encode($data));
		if ($res['code'] != 0) {
			return false;
		}
		$res  = json_decode($res['msg'], true);
		if (!$res || $res['Result'] != 1) {
			return false;
		}
		$userids = array();
		foreach ($res['RobotList'] as $item) {
			$userids[] = $item['Uin'];
		}
		return $userids;
	}
	
	/**
	 * 给指定的直播间新增机器人
	 * @param int    $studioid
	 * @param array  $userids
	 */
	public static function delrobotlist($studioid, $userids=array()) {
		$api = self::imuri().'/delrobotlist';
		if (empty($userids)) {
			$userids = self::getrobotlist($studioid);
		}
		if (!$userids) {
			return;
		}
		$data = array('Count'=>count($userids), 'RobotList'=>array());
		foreach ($userids as $userid) {
			$data['RobotList'][] = array('StudioId'=>$studioid, 'Uin'=>$userid);
		}
		\classlib\request::run($api, json_encode($data));
	}
	
	/**
	 * 异步的HTTP请求信息
	 * @param string $url
	 * @param string $querystr
	 * @param array  $header
	 * @param string $method
	 */
	public static function async($url, $querystr, $header = array(), $method='POST') {
		$uri  = parse_url($url);
		$port = (isset($uri['port']) && $uri['port'] > 0)? $uri['port']:80;
		$fd   = fsockopen($uri['host'], $port, $errno, $errstr, 30);
		if (!$fd) { //请求出现问题的时候
			\classlib\logger::inst()->write($errno.':'.$errstr.':'.$url.':'.$querystr);
			return false;
		}
		$str  = $method.' '.$uri['path']." HTTP/1.1\r\n";
		$str .= 'Host: '.$uri['host']."\r\n";
		foreach ($header as $key=>$vals) {
			$str .= $key.': '.$vals."\r\n";
		}
		$str .= 'Content-Length: '.strlen($querystr)."\r\n";
		$str .= "Connection: Close\r\n\r\n";
		if ($querystr) {
			$str .= $querystr."\r\n";
		}
		fwrite($fd, $str);
		fclose($fd);
		return true;
	}
}